//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package project_git_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/project_dao"
	"atomgit.com/openlinksaas-org/api-server/utils"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_git_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

type ProjectGitApiImpl struct {
	project_git_api.UnimplementedProjectGitApiServer
}

func (apiImpl *ProjectGitApiImpl) AddGitRepo(ctx context.Context, req *project_git_api.AddGitRepoRequest) (*project_git_api.AddGitRepoResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_git_api.AddGitRepoResponse{
			Code:   project_git_api.AddGitRepoResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_git_api.AddGitRepoResponse{
			Code:   project_git_api.AddGitRepoResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_git_api.AddGitRepoResponse{
			Code:   project_git_api.AddGitRepoResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_git_api.AddGitRepoResponse{
			Code:   project_git_api.AddGitRepoResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_git_api.AddGitRepoResponse{
			Code:   project_git_api.AddGitRepoResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	gitRepoId := uuid.NewString()
	nowTime := time.Now().UnixNano() / 1e6
	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_dao.GitRepoDao.Insert(sessCtx, &project_dao.GitRepoInfoDbItem{
			GitRepoId: gitRepoId,
			ProjectId: req.ProjectId,
			BasicInfo: project_dao.BasicGitRepoInfoDbItem{
				Name:   req.BasicInfo.Name,
				GitUrl: req.BasicInfo.GitUrl,
			},
			CreateTime: nowTime,
			UpdateTime: nowTime,
		})
		if err != nil {
			return nil, err
		}
		return &project_git_api.AddGitRepoResponse{
			Code:      project_git_api.AddGitRepoResponse_CODE_OK,
			GitRepoId: gitRepoId,
		}, nil
	})

	if err != nil {
		return nil, err
	}
	return ret.(*project_git_api.AddGitRepoResponse), nil
}

func (apiImpl *ProjectGitApiImpl) UpdateGitRepo(ctx context.Context, req *project_git_api.UpdateGitRepoRequest) (*project_git_api.UpdateGitRepoResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_git_api.UpdateGitRepoResponse{
			Code:   project_git_api.UpdateGitRepoResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_git_api.UpdateGitRepoResponse{
			Code:   project_git_api.UpdateGitRepoResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_git_api.UpdateGitRepoResponse{
			Code:   project_git_api.UpdateGitRepoResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_git_api.UpdateGitRepoResponse{
			Code:   project_git_api.UpdateGitRepoResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_git_api.UpdateGitRepoResponse{
			Code:   project_git_api.UpdateGitRepoResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	exist, err := project_dao.GitRepoDao.Exist(ctx, req.ProjectId, req.GitRepoId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_git_api.UpdateGitRepoResponse{
			Code:   project_git_api.UpdateGitRepoResponse_CODE_NO_GIT_REPO,
			ErrMsg: "Git仓库不存在",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6
	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_dao.GitRepoDao.Update(sessCtx, req.ProjectId, req.GitRepoId,
			&project_dao.BasicGitRepoInfoDbItem{
				Name:   req.BasicInfo.Name,
				GitUrl: req.BasicInfo.GitUrl,
			}, nowTime)
		if err != nil {
			return nil, err
		}
		return &project_git_api.UpdateGitRepoResponse{
			Code: project_git_api.UpdateGitRepoResponse_CODE_OK,
		}, nil
	})

	if err != nil {
		return nil, err
	}
	return ret.(*project_git_api.UpdateGitRepoResponse), nil
}

func (apiImpl *ProjectGitApiImpl) RemoveGitRepo(ctx context.Context, req *project_git_api.RemoveGitRepoRequest) (*project_git_api.RemoveGitRepoResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_git_api.RemoveGitRepoResponse{
			Code:   project_git_api.RemoveGitRepoResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_git_api.RemoveGitRepoResponse{
			Code:   project_git_api.RemoveGitRepoResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_git_api.RemoveGitRepoResponse{
			Code:   project_git_api.RemoveGitRepoResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &project_git_api.RemoveGitRepoResponse{
			Code:   project_git_api.RemoveGitRepoResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(projectItem.OwnerUserId == sessionItem.UserId || roleItem.BasicInfo.Admin) {
		return &project_git_api.RemoveGitRepoResponse{
			Code:   project_git_api.RemoveGitRepoResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	exist, err := project_dao.GitRepoDao.Exist(ctx, req.ProjectId, req.GitRepoId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &project_git_api.RemoveGitRepoResponse{
			Code: project_git_api.RemoveGitRepoResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(context.Background(), func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = project_dao.GitRepoDao.Remove(sessCtx, req.ProjectId, req.GitRepoId)
		if err != nil {
			return nil, err
		}
		return &project_git_api.RemoveGitRepoResponse{
			Code: project_git_api.RemoveGitRepoResponse_CODE_OK,
		}, nil
	})

	if err != nil {
		return nil, err
	}
	return ret.(*project_git_api.RemoveGitRepoResponse), nil
}

func (apiImpl *ProjectGitApiImpl) ListGitRepo(ctx context.Context, req *project_git_api.ListGitRepoRequest) (*project_git_api.ListGitRepoResponse, error) {
	emptyList := []*project_git_api.GitRepoInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_git_api.ListGitRepoResponse{
			Code:         project_git_api.ListGitRepoResponse_CODE_WRONG_SESSION,
			ErrMsg:       "会话不存在",
			RepoInfoList: emptyList,
		}, nil
	}
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_git_api.ListGitRepoResponse{
			Code:         project_git_api.ListGitRepoResponse_CODE_NO_PROJECT,
			ErrMsg:       "项目不存在",
			RepoInfoList: emptyList,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_git_api.ListGitRepoResponse{
			Code:         project_git_api.ListGitRepoResponse_CODE_NO_PERMISSION,
			ErrMsg:       "没有权限",
			RepoInfoList: emptyList,
		}, nil
	} else if err != nil {
		return nil, err
	}

	repoItemList, err := project_dao.GitRepoDao.List(ctx, req.ProjectId)
	if err != nil {
		return nil, err
	}
	repoList := []*project_git_api.GitRepoInfo{}
	for _, repoItem := range repoItemList {
		repoList = append(repoList, repoItem.ToGitRepoInfo())
	}
	return &project_git_api.ListGitRepoResponse{
		Code:         project_git_api.ListGitRepoResponse_CODE_OK,
		RepoInfoList: repoList,
	}, nil
}

func (apiImpl *ProjectGitApiImpl) GetGitRepo(ctx context.Context, req *project_git_api.GetGitRepoRequest) (*project_git_api.GetGitRepoResponse, error) {
	emptyInfo := &project_git_api.GitRepoInfo{
		BasicInfo: &project_git_api.BasicGitRepoInfo{},
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &project_git_api.GetGitRepoResponse{
			Code:     project_git_api.GetGitRepoResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			RepoInfo: emptyInfo,
		}, nil
	}
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &project_git_api.GetGitRepoResponse{
			Code:     project_git_api.GetGitRepoResponse_CODE_NO_PROJECT,
			ErrMsg:   "项目不存在",
			RepoInfo: emptyInfo,
		}, nil
	} else if err == utils.ErrNoRole {
		return &project_git_api.GetGitRepoResponse{
			Code:     project_git_api.GetGitRepoResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			RepoInfo: emptyInfo,
		}, nil
	} else if err != nil {
		return nil, err
	}

	repoItem, err := project_dao.GitRepoDao.Get(ctx, req.ProjectId, req.GitRepoId)
	if err != nil {
		return &project_git_api.GetGitRepoResponse{
			Code:     project_git_api.GetGitRepoResponse_CODE_NO_GIT_REPO,
			ErrMsg:   "Git仓库不存在",
			RepoInfo: emptyInfo,
		}, nil
	}
	return &project_git_api.GetGitRepoResponse{
		Code:     project_git_api.GetGitRepoResponse_CODE_OK,
		RepoInfo: repoItem.ToGitRepoInfo(),
	}, nil
}
